#include <p_std.h>
#include <p_file.h>
#include <wlib.h>

LOCAL_D VOID *timH;
LOCAL_D WORD timstat;
LOCAL_D WORD counter;
LOCAL_D ULONG timint;

#define NUM_STEPS    9
#define STEP_WIDTH  16
#define BAR_LEFT     8
#define BAR_WIDTH  144

LOCAL_C VOID GetBarChartRect(P_RECT *pbox)
    {
    pbox->tl.x=BAR_LEFT;
    pbox->br.x=BAR_LEFT+BAR_WIDTH;
    pbox->br.y=80-4-1;
    pbox->tl.y=80-4-1-6;
    }

LOCAL_C VOID QueueTimer(VOID)
    {
    p_ioa4(timH,P_FRELATIVE,&timstat,&timint);
    }

LOCAL_C VOID CancelTimer(VOID)
    {
    p_iow2(timH,P_FCANCEL);
    p_waitstat(&timstat);
    }

LOCAL_C VOID CentrePrint(INT y1,INT y2,INT ascent,TEXT *pb)
    {
    P_RECT box;

    box.tl.x=4;
    box.br.x=160-4;
    box.tl.y=y1;
    box.br.y=y2;
    gPrintBoxText(&box,ascent,G_TEXT_ALIGN_CENTRE,0,pb,p_slen(pb));
    }

LOCAL_C VOID SetFont(INT font)
    {
    G_GC gc;

    gc.font=font;
    gSetGC(0,G_GC_MASK_FONT,&gc);
    }

LOCAL_C VOID SetStyle(INT style)
    {
    G_GC gc;

    gc.style=style;
    gSetGC(0,G_GC_MASK_STYLE,&gc);
    }

LOCAL_C VOID TellCounter(VOID)
    {
    TEXT buf[10];

    p_atos(&buf[0],"%d",counter);
    SetStyle(G_STY_DOUBLE|G_STY_BOLD);
    CentrePrint(46,64,16,&buf[0]);
    SetStyle(G_STY_NORMAL);
    }

LOCAL_C VOID DrawBar(VOID)
    {
    P_RECT box;

    GetBarChartRect(&box);
    if (!counter)
        gClrRect(&box,G_TRMODE_CLR);
    else
        {
        box.br.x=BAR_LEFT+counter*STEP_WIDTH;
        gFillPattern(&box,WS_BITMAP_GREY,G_TRMODE_REPL);
        }
    TellCounter();
    }

LOCAL_C VOID TellTimint(VOID)
    {
    TEXT buf[30];

    p_atos(&buf[0],"Ticking every %d secs/10",(INT)timint);
    CentrePrint(4,12,7,&buf[0]);
    }

typedef struct
    {
    TEXT *msg;
    WORD x;
    WORD y;
    } CHOICE;

LOCAL_D CHOICE ch[4]=
    {
    "(F) Faster",12,20,
    "(S) Slower",12,30,
    "(Z) Zero",88,20,
    "(X) Exit",88,30
    };

LOCAL_C VOID DisplayChoice(INT i)
    {
    P_RECT box;
    TEXT *pb;

    box.tl.x=ch[i].x;
    box.tl.y=ch[i].y;
    box.br.x=box.tl.x+65;
    box.br.y=box.tl.y+8;
    pb=ch[i].msg;
    gPrintBoxText(&box,7,G_TEXT_ALIGN_LEFT,0,pb,p_slen(pb));
    }

LOCAL_C VOID DisplayChoices(VOID)
    {
    INT i;

    for (i=0; i<4; i++)
        DisplayChoice(i);
    }

#define S3_FONT     WS_FONT_BASE+4

LOCAL_C VOID Flash(INT i)
    {
    P_EXTENT ext;

    ext.tl.x=ch[i].x-1;
    ext.tl.y=ch[i].y-1;
    ext.width=gTextWidth(S3_FONT,G_STY_NORMAL,ch[i].msg,3)+1;
    ext.height=9;
    gInvObloid(&ext);
    wFlush();
    p_sleep(2);
    gInvObloid(&ext);
    }

GLDEF_C VOID main(VOID)
    {
    WS_EV event;
    P_RECT box;
    WORD wactive;

    wStartup();
    gBorder(W_BORD_CORNER_4);
    GetBarChartRect(&box);
    p_insrec(&box,-1,-1);
    gBorderRect(&box,W_BORD_CORNER_1);
    SetFont(S3_FONT);
    DisplayChoices();
    p_open(&timH,"TIM:",-1);
    timint=10;
    TellTimint();
    QueueTimer();
    wactive=FALSE;
    FOREVER
        {
        if (wactive)
            wFlush();
        else
            {
            wGetEvent(&event);
            wactive=TRUE;
            }
        p_iowait();
        if (event.type==E_FILE_PENDING)
            {
            if (counter++==NUM_STEPS)
                counter=0;
            DrawBar();
            QueueTimer();
            continue;
            }
        wactive=FALSE;
        if (event.type==WM_KEY)
            {
            switch (event.p.key.keycode)
                {
            case 'x':
                Flash(3);
                p_exit(0);
            case 'z':
                Flash(2);
                CancelTimer();
                counter=0;
                DrawBar();
                QueueTimer();
                break;
            case 'f':
                Flash(0);
                if (timint!=1)
                    {
                    timint--;
                    TellTimint();
                    }
                break;
            case 's':
                Flash(1);
                timint++;
                TellTimint();
                }
            }
        }
    }
